/**
 * 
 */
package com.xb.demox.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.config.MethodInvokingFactoryBean;

/**
 * 写一个代理类
 * 
 * @author kexue
 *
 */
public class TestTemplateMethodInvokingFactoryBean extends MethodInvokingFactoryBean {

	private Class<?> serviceInterface;

	public Class<?> getServiceInterface() {
		return serviceInterface;
	}

	public void setServiceInterface(Class<?> serviceInterface) {
		this.serviceInterface = serviceInterface;
	}

	public Object getServiceProxy() {
		return serviceProxy;
	}

	public void setServiceProxy(Object serviceProxy) {
		this.serviceProxy = serviceProxy;
	}

	public TestTemplate getTeplateInstance() {
		return new TestTemplate();
	}

	private Object serviceProxy;

	@Override
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		if (getServiceInterface() == null) {
			throw new IllegalArgumentException("Property 'serviceInterface' is required");
		}
		
		DynamicInvocationHandler h = new DynamicInvocationHandler(super.getTargetObject());
		h.setBeforeInterceptors(Arrays.asList(new Interceptor[]{new Interceptor() {
			public void interceptor(MethodInvokerContext context) {
				// TODO Auto-generated method stub
				
			}
		}}));
		
		this.serviceProxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
				new Class<?>[] { getServiceInterface() }, h);

	}

	@Override
	public Object getObject() {
		return this.serviceProxy;
	}

	@Override
	public Class<?> getObjectType() {
		return getServiceInterface();
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

	class DynamicInvocationHandler implements InvocationHandler {

		private Object targetSource;

		private List<Interceptor> beforeInterceptors;
		private List<Interceptor> afterInterceptors;
		
		public Object getTargetSource() {
			return targetSource;
		}

		public void setTargetSource(Object targetSource) {
			this.targetSource = targetSource;
		}

		public List<Interceptor> getBeforeInterceptors() {
			return beforeInterceptors;
		}

		public void setBeforeInterceptors(List<Interceptor> beforeInterceptors) {
			this.beforeInterceptors = beforeInterceptors;
		}

		public List<Interceptor> getAfterInterceptors() {
			return afterInterceptors;
		}

		public void setAfterInterceptors(List<Interceptor> afterInterceptors) {
			this.afterInterceptors = afterInterceptors;
		}

		public DynamicInvocationHandler(Object targetSource) {
			this.targetSource = targetSource;
		}

		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			MethodInvokerContext context =new MethodInvokerContext(proxy.getClass(),method,args,targetSource);

			if (beforeInterceptors != null && beforeInterceptors.size() != 0) {
				for(Interceptor interceptor:beforeInterceptors){
					interceptor.interceptor(context);
				}
			}
			
			Object result = method.invoke(targetSource, args);
			
			if (afterInterceptors != null && afterInterceptors.size() != 0) {
				for(Interceptor interceptor:afterInterceptors){
					interceptor.interceptor(context);
				}
			}
			return result;
		}
	}
}
